const express = require("express");
const util = require("../common/util");
const ReservationDB = require("../model/db/reservation");

/**  
 * 新增预约  
 * @param {express.Request} req 请求  
 * @param {express.Response} res 响应  
 */
async function add(req, res) {
  try {
    const reservation = {
      userId: req.session.user.id,
      itemId: req.body.itemId,
      reservationTime: new Date(req.body.reservationTime || Date.now()).toISOString().slice(0, 19).replace('T', ' '),
      retrieveTime: new Date(req.body.retrievalTime || Date.now()).toISOString().slice(0, 19).replace('T', ' '),
      // storageTime: new Date(req.body.storageTime || Date.now()).toISOString().slice(0, 19).replace('T', ' '),
      note: req.body.note,
    };

    const db = ReservationDB.getInstance();

    const lastID = await db.add(reservation);

    util.log(`新增预约信息：lastID=${lastID}`);

    res.json(util.FormatJSONData(201, `新增预约信息成功`, { lastID }));
  } catch (error) {
    /// 处理错误
    util.err(error);

    // 判断是否是外键约束错误
    if (error.code === 'ER_NO_REFERENCED_ROW_2') {
      // 返回更友好的错误响应
      res.status(400).json(util.FormatJSONData(400, '预约失败，请检查物品ID是否正确', error));
    } else {
      // 返回服务器内部错误响应
      res.status(500).json(util.FormatJSONData(500, '服务器内部错误', error));
    }
  }
}

/**
 * 更新预约记录
 * @param {*} req 
 * @param {*} res 
 */
async function update(req, res) {
  try {
    // 构造更新预约的 SQL 语句
    const sql = `UPDATE reservations SET
          reservation_time = ?,
          retrieve_time = ?,
          confirmed = ?,
          status = ?,
          note = ?,
          delivery_person_id = ?
        WHERE id = ?;`;

    // 提取预约数据作为参数
    const params = {
      reservationTime: req.body.reservationTime,
      retrieveTime: req.body.retrieveTime,
      confirmed: req.body.confirmed,
      status: req.body.status,
      note: req.body.note,
      deliveryPersonId: req.body.deliveryPersonId,
      id: req.params.id
    }

    // 获取预约数据库实例
    const db = ReservationDB.getInstance();

    // 执行更新预约操作
    const affectedRows = await db.update(params);

    // 返回受影响的行数
    res.json(util.FormatJSONData(200, `更新预约信息成功`, { affectedRows }));
  } catch (error) {
    // 处理错误
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, '服务器内部错误', error));
  }
}

/**
 * 更新个人预约记录
 * @param {Request} req Express请求对象，包含请求体和参数
 * @param {Response} res Express响应对象，用于发送响应
 */
async function updateSelf(req, res) {
  // 使用匿名异步函数来处理异步操作
  try {
    // 创建一个包含要更新的预约信息的对象
    const updateData = {
      reservationTime: req.body.reservationTime,
      retrieveTime: req.body.retrieveTime,
      confirmed: req.body.confirmed,
      note: req.body.note,
      id: req.params.id,
    };

    // 过滤掉updateData中值为undefined的属性，以避免无效数据
    const filteredData = Object.fromEntries(
      Object.entries(updateData).filter(([_, v]) => v !== undefined)
    );

    // 获取数据库实例
    const db = ReservationDB.getInstance();

    // 根据ID查找预约记录
    let reservation = await db.find(req.params.id);

    // 如果找不到预约记录，返回404错误
    if (!reservation) {
      return res.status(404).json({ error: '预约记录未找到' });
    }

    // 检查是否为预约记录的所有者，否则返回403错误
    if (reservation.reserver_id !== req.session.user.id) {
      return res.status(403).json({ error: '无权限更新预约记录' });
    }

    // 使用filteredData更新预约记录
    const affectedRows = await db.updateSelf(filteredData);
    // 检查受影响的行数，如果为0，则返回特定的消息
    if (affectedRows === 0) {
      return res.status(204).json(util.FormatJSONData(200, '没有数据被修改', { affectedRows }));
    }

    // 返回200状态码，表示成功并附带受影响的行数
    res.json(util.FormatJSONData(200, `更新预约信息成功`, { affectedRows }));
  } catch (error) {
    if (error.message === '没有数据被修改') {
      res.status(204).json(util.FormatJSONData(204, error.message, { affectedRows: 0 }));
    } else {
      util.err(error);
      res.status(500).json(util.FormatJSONData(500, '服务器内部错误', error));
    }
  }
}
/**
* 获取指定ID的物品
* @param {express.Request} req 请求
* @param {express.Response} res 响应
*/
function find(req, res) {
  (async function () {
    const db = ReservationDB.getInstance();
    const result = await db.find(req.params.id);
    util.logFormat(`获取【${req.params.id}】预约信息：%O`, result);
    res.json(util.FormatJSONData(200, `获取指定预约信息【${req.params.id}】成功`, result));
  })();
}

/**
* 获取预约列表
* @param {express.Request} req 请求
* @param {express.Response} res 响应
*/
async function findAll(req, res) {
  const limit = req.query.limit ? parseInt(req.query.limit) : -1;
  const offset = req.query.offset ? parseInt(req.query.offset) : -1;

  const db = ReservationDB.getInstance();
  const result = await db.findAll(limit, offset);

  //await db.close();
  util.logFormat(
    `获取【limit=${limit}&offset=${offset}】预约列表信息：%O`,
    result
  );
  res.json(util.FormatJSONData(200, `获取预约列表信息成功`, result));
}

/**
 * 删除指定预约信息
 * @param {*} req 
 * @param {*} res 
 */
async function remove(req, res) {
  try {
    // 假设 itemId 是通过请求体传递的  
    const reservationId = req.params.id;

    // 这里可以添加更多的验证逻辑，例如检查 ReservationId 是否为数字、是否在允许的范围内等  
    if (Number.isNaN(reservationId)) {
      throw new Error('Invalid ReservationId');
    }

    const db = ReservationDB.getInstance();
    const reservation = await db.find(reservationId);
    if (!reservation) {
      throw new Error('Reservation not found');
    }
    if (reservation.user_id === req.session.user.id || req.session.user.role === 1) {
      const changes = await db.remove(reservationId);
      // 检查是否实际有记录被删除  
      if (changes === 0) {
        throw new Error('Reservation not found');
      }

      util.log(`删除指定预约信息：changes=${changes}`);
      res.json(util.FormatJSONData(204, '删除指定预约信息成功', { changes }));
    } else {
      res.json(util.FormatJSONData(403, `无权限删除预约信息`, {}));
    }



  } catch (err) {
    // 在这里处理错误，并返回适当的HTTP响应  
    util.log(`删除预约时出错：${err.message}`);
    res.status(400).json(util.FormatJSONData(400, '删除预约失败', { error: err.message }));
  }
}



module.exports = {
  add,
  update,
  find,
  findAll,
  remove,
  updateSelf,
}